﻿using ORM.Attribute;
using ORM.Exception;
using ORM.Util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ORM.Model
{
    public class MapperEntity
    {
        private Type EnityType { set; get; }
        public string TableName { set; get; }
        public string KeyName { set; get; }
        public PropertyInfo[] PropertyList { set; get; }
        public PropertyInfo[] MapPropertyList { set; get; }
        public List<string> IgnoreFieldList { set; get; }
        public Dictionary<string, PropertyEmit> EmitDic { set; get; }
        public MapperEntity(Type EnityType)
        {
            this.EnityType = EnityType;
            IgnoreFieldList = new List<string>();
            EmitDic = new Dictionary<string, PropertyEmit>();
        }

        public void Init()
        {
            this.TableName = EnityType.Name;
            this.PropertyList = EnityType.GetProperties();
            PropertyInfo[] key = PropertyList.Where(a => a.GetCustomAttribute<Key>() != null).ToArray();
            if (key.Count() == 0)
            {
                throw new EntityNotMapperKeyException();
            }
            else
            {
                KeyName = key[0].Name;
            }
            PropertyInfo[] ignore = PropertyList.Where(a => a.GetCustomAttribute<Ignore>() != null).ToArray();
            foreach (PropertyInfo item in ignore)
            {
                IgnoreFieldList.Add(item.Name);
            }

            List<PropertyInfo> MapList = new List<PropertyInfo>();
            foreach (PropertyInfo item in PropertyList)
            {
                if (!IgnoreFieldList.Contains(item.Name))
                {
                    MapList.Add(item);
                    PropertyEmit pe = new PropertyEmit();
                    pe.EmitGetter = EmitBuilder.EmitGetter(EnityType, item.Name);
                    pe.EmitSetter = EmitBuilder.EmitSetter(EnityType, item.Name);
                    EmitDic.Add(item.Name, pe);
                }
            }
            MapPropertyList = MapList.ToArray();
        }

        public T MapInstance<T>(DataRow Row)
        {
            //获取空构造函数
            ConstructorInfo ct = EnityType.GetConstructor(System.Type.EmptyTypes);
            //new 对象
            T entity = (T)ct.Invoke(null);
            foreach (PropertyInfo item in PropertyList)
            {
                if (!IgnoreFieldList.Contains(item.Name))
                {
                    if (Convert.IsDBNull(Row[item.Name]) && EmitDic.ContainsKey(item.Name))
                    {
                        var fieldvalue = item.PropertyType.IsValueType ? Activator.CreateInstance(item.PropertyType) : null;
                        EmitDic[item.Name].EmitSetter(entity, fieldvalue);
                    }
                    else
                    {
                        EmitDic[item.Name].EmitSetter(entity, Row[item.Name]);
                    }

                }
            }
            return entity;
        }

    }
}
